// general PID
#ifndef PID_HPP
#define PID_HPP

#include "stm32f10x.h" // introduce the stm32f10x.h for TIM component
#include <stdint.h>

// PID作用方式，分正作用和负作用
typedef enum {
  PID_POSITIVE_EFFECT = -1, // 正作用，PID输出与偏差值反向
  PID_NEGATIVE_EFFECT = 1   // 负作用，PID输出与偏差值正向
} PIDActionMode;

typedef struct {
  volatile float target,    // 目标值
      measured,             // 测量值
      output;               // 输出
  float cell,               // 输出上限
      floor,                // 输出下限
      intCell,              // 积分上限
      intFloor;             // 积分下限
  float kp;                 // 比例系数
  float ti,                 // 积分时间常数（ms）
      td,                   // 微分时间常数（ms）
      period;               // PID执行周期（ms）
  char limitEnabled,        // 输出限幅开关
      intLimitEnabled,      // 积分限幅开关
      holdOn;               // 手动模式开关
  PIDActionMode actionMode; // 正反作用

  // private:
  float _int,               // 积分部分
      _err,                 // 偏差
      _prevErr;             // 前一次的偏差
  TIM_TypeDef *_timer;      // 绑定的定时器
  uint32_t _TIMReloadCount; // 计数器置数中断多少次执行一次PID
  volatile uint32_t _currentCount; // 当前置数中断多少次

} PID;

PID *new_PID(void);
void delete_PID(PID *this);

void PID_Init(PID *this);
void PID_Config(PID *this, float kp, float ti_ms, float td_ms, int T_ms,
                PIDActionMode mode, TIM_TypeDef *timer);

void PID_LimitEnable(PID *this);
void PID_LimitDisable(PID *this);
void PID_LimitConfig(PID *this, float cell, float floor);
void PID_IntLimitEnable(PID *this);
void PID_IntLimitDisable(PID *this);
void PID_IntLimitConfig(PID *this, float cell, float floor);

void PID_SetMeasured(PID *this, float value);
void PID_SetTarget(PID *this, float value);
void PID_SetOutput(PID *this, float value);

float PID_GetMeasured(PID *this);
float PID_GetTarget(PID *this);
float PID_GetOutput(PID *this);

void PID_HoldOn(PID *this);
void PID_HoldOff(PID *this);
void PID_Clear(PID *this);

void PID_Step(PID *this);

#endif // PID_H
